home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / xautolk.zip / XAUTOLK < prev   
Text File  |  1993-01-28  |  55KB  |  1,925 lines

  1.  
  2. Hello,
  3.  
  4.  
  5. This is patchlevel 8 of xautolock, the program which monitors console
  6. activity, and starts up a program of  your choice if nothing  happens
  7. during a certain time interval.  
  8.  
  9.  
  10. What's new?
  11. -----------
  12.  
  13.  - It supports multiheaded displays.
  14.  - It now uses the X resource database.
  15.  - The copyright notice has been changed considerably.
  16.  - The notification margin and bell percentage can be specified by
  17.    the user.
  18.  - It no longer steals events from windowmanagers that use a pseudo
  19.    root window.
  20.  - It no longer needs to get pointer events, so the chances of it
  21.    messing up event propagation have become even smaller.
  22.  - It can be disabled or activated by moving the pointer into one
  23.    of the corners of the display. This is highly customizable.
  24.  - It can be disabled (and re-enabled) by sending it a SIGHUP.
  25.  - By default, it now closes stdout and stderr, so you no longer
  26.    get zillions of error messages if you manually lock your display.
  27.  - The code is has become more foolproof (patchlevel 7 users
  28.    will have a hard time recognizing it :-).
  29.  
  30.  
  31. What hasn't been done yet?
  32. --------------------------
  33.  
  34.  - It still is contained in a single source file.
  35.  
  36.  
  37. Important
  38. ---------
  39.  
  40. Users of swm and tvtwm, (especially on Sparcs) are adviced to read
  41. the WARNING section in the README file.
  42.  
  43.  
  44.                           SDT & MCE
  45.  
  46. 8<- CUT HERE ---------------------------------------------------------
  47. #! /bin/sh
  48. # This is a shell archive, meaning:
  49. # 1. Remove everything above the #! /bin/sh line.
  50. # 2. Save the resulting text in a file.
  51. # 3. Execute the file with /bin/sh (not csh) to create the files:
  52. #    xautolock
  53. # This archive created: Fri Jun 19 22:28:31 1992
  54. export PATH; PATH=/bin:$PATH
  55. if test ! -d 'xautolock'
  56. then
  57.     echo shar: creating directory "'xautolock'"
  58.     mkdir 'xautolock'
  59. fi
  60. echo shar: entering directory "'xautolock'"
  61. cd 'xautolock'
  62. echo shar: extracting "'xautolock.man'" '(5719 characters)'
  63. if test -f 'xautolock.man'
  64. then
  65.     echo shar: will not over-write existing file "'xautolock.man'"
  66. else
  67. sed 's/^X//' << \SHAR_EOF > 'xautolock.man'
  68. X.TH xautolock l
  69. X
  70. X
  71. X.SH NAME
  72. X
  73. Xxautolock \- locks X display after a period of inactivity
  74. X
  75. X
  76. X.SH SYNOPSIS 
  77. X
  78. X\fBxautolock\fR [\fB\-help\fR] [\fB\-version\fR] 
  79. X[\fB\-time\fR \fIminutes\fR] [\fB\-locker\fR \fIlocker\fR]
  80. X          [\fB\-notify \fImargin\fR] [\fB\-bell \fIpercent\fR]
  81. X[\fB\-corners\fR \fIxxxx\fR]
  82. X          [\fB\-cornerdelay\fR \fIsecs\fR]
  83. X[\fB\-cornersize\fR \fIpixels\fR] [\fB\-noclose\fR]
  84. X.br 
  85. X
  86. X
  87. X.SH DESCRIPTION 
  88. X
  89. XWhen xautolock is started, it monitors the user activity on the
  90. Xworkstation. When no activity is detected within \fIminutes\fR
  91. Xminutes, the screen is automatically locked, using the screen
  92. Xlocker specified with the \fI\-locker\fR option. xautolock is
  93. Xcapable of managing multiheaded displays.
  94. X
  95. XIn the presence of the \fI\-notify\fR option, a warning signal will
  96. Xbe issued \fImargin\fR seconds before starting the locker. The
  97. X\fI\-bell\fR option specifies the loudness of the signal in
  98. X\fIpercent\fR.
  99. X
  100. XYou can tell xautolock to take special actions when you move
  101. Xthe mouse into one of the corners of the display and leave it
  102. Xthere, by using the \fI\-corners\fR,
  103. X\fI\-cornerdelay\fR and \fI\-cornersize\fR
  104. Xoptions. This works as follows :
  105. X
  106. XThe \fIxxxx\fR argument to the \fI\-corners\fR option must consist
  107. Xof exactly 4 characters from the following set : '0', '+', '-'.
  108. XEach one of these specifies what xautolock should do when the mouse
  109. Xenters a small square area located in each of the corners of the
  110. Xscreen. The corners are considered in the
  111. Xfollowing order : top left, top right, bottom left, bottom right.
  112. XA '0' indicates that xautolock should ignore the corner.
  113. XA '+' indicates that xautolock should start the \fIlocker\fR 
  114. Xafter \fIsecs\fR seconds, unless the mouse is moved, or keyboard
  115. Xinput is received. A '-' indicates that xautolock not start the
  116. X\fIlocker\fR at all. The \fIpixels\fR argument specifies the
  117. Xsize in pixels of the corner areas.
  118. X
  119. XBy default xautolock closes stdout and stderr. This prevents the
  120. Xscreenlocker from writing error messages to these files in case
  121. Xyou manually lock your display. The \fI\-noclose\fR option causes
  122. Xxautolock not to close stdout and stderr. This can be used for
  123. Xdebugging.
  124. X
  125. XYou can also disable xautolock by sending it a SIGHUP
  126. Xsignal. When disabled, it will not attempt to start the
  127. Xscreenlocker. To re-enable it, send it another SIGHUP. This 
  128. Xmethod is preferable to using SIGSTOP and SIGCONT, because
  129. Xwhile SIGHUPped, xautolock will still be emptying its 
  130. Xevent queue.
  131. X
  132. X
  133. X.SH OPTIONS
  134. X
  135. X.TP 14
  136. X\fB\-help\fR
  137. XPrint a help message and exit.
  138. X.TP 
  139. X\fB\-version\fR
  140. XPrint the version number and exit.
  141. X.TP 
  142. X\fB\-time\fR
  143. XSpecifies the time-out interval. The default is 10 minutes,
  144. Xthe minimum is 1 minute and the maximum is 1 hour.
  145. X.TP 
  146. X\fB\-locker\fR
  147. XSpecifies the screen locker to be used. The default is
  148. X"xlock 2>&- 1>&-". Your PATH is used to locate the program.
  149. XNotice that if \fIlocker\fR contains several words, it must
  150. Xbe specified between quotes.
  151. X.TP 
  152. X\fB\-notify\fR
  153. XWarn the user \fImargin\fR seconds before locking. The
  154. Xdefault is not to warn the user.
  155. X.TP
  156. X\fB\-bell\fR
  157. XSpecifies the loudness of the notification signal. The default
  158. Xis 40 percent. This option is only usefull in conjunction with
  159. X\fI\-notify\fR.
  160. X.TP 
  161. X\fB\-corners\fR
  162. XDefine special actions to be taken when the mouse
  163. Xenters one of the corners of the display. The default is 0000,
  164. Xwhich means that no special actions are taken.
  165. X.TP 
  166. X\fB\-cornerdelay\fR
  167. XSpecifies the number of seconds to wait
  168. Xbefore reacting to a '+' corner. The default is 5 seconds.
  169. X.TP 
  170. X\fB\-cornersize\fR
  171. XSpecifies the size in pixels of the corner areas. The default is
  172. X10 pixels.
  173. X.TP 
  174. X\fB\-noclose\fR
  175. XDon't close stdout and stderr.
  176. X
  177. X
  178. X.SH RESOURCES
  179. X
  180. X.TP 14
  181. X.B time 
  182. XSpecifies the time out period.
  183. X.TP 14
  184. X.B locker 
  185. XSpecifies the screen locker. No quotes are needed, even if
  186. Xyour screen locker command contains several words.
  187. X.TP 14
  188. X.B notify 
  189. XSpecifies the notification margin.
  190. X.TP 14
  191. X.B bell 
  192. XSpecifies the notification loudness.
  193. X.TP 14
  194. X.B corners 
  195. XSpecifies the corner behaviour.
  196. X.TP 14
  197. X.B cornersize 
  198. XSpecifies the size of the corner areas.
  199. X.TP 14
  200. X.B cornerdelay 
  201. XSpecifies the delay of a '+' corner.
  202. X.TP 14
  203. X.B noclose 
  204. XDon't close stdout and stderr.
  205. X
  206. X.TP 0
  207. XResources can be specified in your \fI~/.Xdefaults\fR file either
  208. Xfor class \fIXautolock\fR, or for whatever name you renamed
  209. Xxautolock to. For example : if you have two copies of xautolock,
  210. Xone called "xfreeze", and one called "xmonitor", then both will
  211. Xunderstand the following :
  212. X
  213. X  Xautolock.corners: ++++
  214. X
  215. XIn addition, "xfreeze" will understand :
  216. X
  217. X  xfreeze.cornersize: 10
  218. X
  219. Xwhile "xmonitor" will understand :
  220. X
  221. X  xmonitor.cornersize: 5
  222. X
  223. X
  224. X.SH KNOWN\ BUGS 
  225. X
  226. Xxautolock does not check whether \fIlocker\fR is available.
  227. X
  228. XThe xautolock resources have no resource class. 
  229. X
  230. X
  231. X.SH COPYRIGHT
  232. X
  233. XCopyright 1990, 1992 by S. De Troch and MCE.
  234. X
  235. XPermission to use, copy, modify and distribute this software and the
  236. Xsupporting documentation without fee is hereby granted, provided that :
  237. X
  238. X 1 : Both the above copyright notice and this permission notice
  239. X     appear in all copies of both the software and the supporting
  240. X     documentation.
  241. X 2 : You don't make a profit out of it.
  242. X
  243. XTHE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  244. XINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
  245. XEVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  246. XDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
  247. XOR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  248. XTORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  249. XPERFORMANCE OF THIS SOFTWARE.
  250. X
  251. X
  252. X.SH AUTHORS   
  253. X
  254. XStefan De Troch (detroch@imec.be),
  255. XMichel Eyckmans (eyckmans@imec.be).
  256. X
  257. X
  258. X.SH SPECIAL\ THANKS\ TO
  259. X
  260. XKris Croes (croes@imec.be).
  261. SHAR_EOF
  262. if test 5719 -ne "`wc -c < 'xautolock.man'`"
  263. then
  264.     echo shar: error transmitting "'xautolock.man'" '(should have been 5719 characters)'
  265. fi
  266. fi # end of overwriting check
  267. echo shar: extracting "'Imakefile'" '(498 characters)'
  268. if test -f 'Imakefile'
  269. then
  270.     echo shar: will not over-write existing file "'Imakefile'"
  271. else
  272. sed 's/^X//' << \SHAR_EOF > 'Imakefile'
  273. X#
  274. X#  Uncomment this if your compiler supports prototypes.
  275. X#
  276. X#  PROTOTYPES = -DHasPrototypes
  277. X
  278. X#ifdef HasVoidSignalReturn
  279. X   VOIDSIGNAL = -DHasVoidSignalReturn
  280. X#endif /* HasVoidSignalReturn */
  281. X
  282. X#if SunOSPlatform == YES
  283. X#
  284. X#  Circumvent a bug in the sun4 optimizer
  285. X#
  286. X  CDEBUGFLAGS = -g
  287. X#endif /* SunOSPlatform */
  288. X
  289. X      DEFINES = $(PROTOTYPES) $(VOIDSIGNAL) 
  290. XSYS_LIBRARIES = -lX11 
  291. X         HDRS = patchlevel.h 
  292. X         SRCS = xautolock.c 
  293. X         OBJS = xautolock.o 
  294. X
  295. XSimpleProgramTarget(xautolock)
  296. SHAR_EOF
  297. if test 498 -ne "`wc -c < 'Imakefile'`"
  298. then
  299.     echo shar: error transmitting "'Imakefile'" '(should have been 498 characters)'
  300. fi
  301. fi # end of overwriting check
  302. echo shar: extracting "'README'" '(4557 characters)'
  303. if test -f 'README'
  304. then
  305.     echo shar: will not over-write existing file "'README'"
  306. else
  307. sed 's/^X//' << \SHAR_EOF > 'README'
  308. XPURPOSE
  309. X=======
  310. X
  311. XXautolock is a program which monitors console activity, and starts up
  312. Xa program of  your choice if  nothing  happens  during a certain time
  313. Xinterval.  You can use this to automatically start up a screen locker
  314. Xin case you tend  to forget to do so  manually before having a coffee
  315. Xbreak.
  316. X
  317. XHARDWARE PLATFORMS
  318. X==================
  319. X
  320. XWe have used  xautolock  on the following hardware without problems :
  321. X
  322. XDECstation 3100 to 5500
  323. XHP Apollo 9000/4xx (Sr10)
  324. XSony News 1800
  325. XSparc II
  326. XVAXen (Ultrix)
  327. X
  328. XOther people have reported that it should also work on :
  329. X
  330. XSun386
  331. XIBM RS/6000
  332. XVAXstation 3100 
  333. X
  334. XAn  earlier  version also ran on  the following machinery,  but we no
  335. Xlonger have those, so testing it was a bit difficult :-). 
  336. X
  337. XSun 3/60
  338. XApollo 3000 to 4500
  339. X
  340. XHOW TO USE IT
  341. X=============
  342. XJust read the man page, it's really simple.
  343. X
  344. X
  345. XHOW IT WORKS
  346. X============
  347. X
  348. XWhen  xautolock  starts  executing,  it  traverses  the  window tree, 
  349. Xselects  SubstructureNotify  on all windows and adds each window to a
  350. Xtemporary list.  About +- 30 seconds later,  it scans this list,  and
  351. Xnow  asks for KeyPress events.  However,  it takes care to  interfere 
  352. Xas litle as possible  with  the event propagation mechanism.  This is
  353. Xthe reason for the delay between the moment  xautolock learns about a
  354. Xnew window (and consequently asks for  SubstructureNotify events) and
  355. Xthe moment it asks for KeyPress.  Whenever a new window is created, a
  356. Xsimilar process takes place.
  357. X
  358. XIn addition, xautolock issues a  QueryPointer  request once a second,
  359. Xin order to find out wether the pointer has moved.
  360. X
  361. XIf nothing happens within a user-specified period of time,  xautolock
  362. Xwill fire up a program  which is supposed  to lock the screen.  While
  363. Xthis program is running, xautolock itself remains on the look-out for
  364. Xuser interaction.
  365. X
  366. XIn contradiction  to what many people  believe,  this scheme does not
  367. Xcause a noticeable overhead. 
  368. X
  369. X
  370. XCOMPILING XAUTOLOCK
  371. X===================
  372. X
  373. XXautolock  should  compile  straight  out of  the box.  Just  do  the
  374. Xfollowing :
  375. X
  376. X 1 : Type 
  377. X
  378. X      xmkmf 
  379. X      make
  380. X      make install
  381. X      make clean 
  382. X
  383. X 2 : Have fun.
  384. X
  385. XKNOWN BUGS
  386. X==========
  387. X
  388. XIf,  when creating  a window,  an application  waits for more than 30
  389. Xseconds before calling XSelectInput (),  xautolock may interfere with
  390. Xthe  event propagation  mechanism.  In order to minimize  the risk of
  391. Xthis happening,  an extra delay of 20 seconds  has been inserted into
  392. Xthe   xautolock  initialization  sequence.   This  was  done  because
  393. Xxautolock is most likely to be started automatically when a user logs
  394. Xin, and that process can be rather time-consuming.
  395. X
  396. XXautolock  does not check whether the screenlocker specified actually
  397. Xis available.
  398. X
  399. XThe xautolock resources have no resource class.
  400. X
  401. XIf you can find others, please send e-mail to one of the authors.
  402. X
  403. X
  404. XWARNING
  405. X=======
  406. X
  407. XThere  is  a  bug  in  the  event management code  of some  X servers
  408. X(amongst  which  both  X11R4  and X11R5  on Sparc).  If you are using 
  409. Xpatchlevel  7  of  xautolock,  it is best to reset  the server before
  410. Xswitching to patchlevel 8.  If you fail to do so, an old patchlevel 7
  411. Xbug may still show up.  (Some keybaord events were being  hijacked by
  412. Xpatchlevel 7 of xautolock, particularly when using tvtwm). 
  413. X
  414. X
  415. XCOPYRIGHT
  416. X=========
  417. XCopyright 1990, 1992 by S. De Troch and MCE.
  418. X
  419. XPermission to use, copy, modify and distribute this software and the
  420. Xsupporting documentation without fee is hereby granted, provided that :
  421. X
  422. X 1 : Both the above copyright notice and this permission notice
  423. X     appear in all copies of both the software and the supporting
  424. X     documentation.
  425. X 2 : You don't make a profit out of it.
  426. X
  427. XDISCLAIMER
  428. X==========
  429. X
  430. XTHE AUTHORS  DISCLAIM  ALL WARRANTIES  WITH  REGARD TO THIS SOFTWARE,
  431. XINCLUDING  ALL IMPLIED WARRANTIES OF MERCHANTABILITY  AND FITNESS, IN
  432. XNO  EVENT  SHALL THEY   BE  LIABLE  FOR   ANY  SPECIAL,  INDIRECT  OR
  433. XCONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS
  434. XOF  USE,  DATA  OR  PROFITS,   WHETHER  IN  AN  ACTION  OF  CONTRACT,
  435. XNEGLIGENCE  OR   OTHER   TORTIOUS  ACTION,   ARISING  OUT  OF  OR  IN
  436. XCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  437. X
  438. XAUTHORS
  439. X=======
  440. X
  441. XXautolock was conceived, written and performed by :
  442. X
  443. X Stefan De Troch             detroch@imec.be
  444. X Michel Eyckmans (MCE)       eyckmans@imec.be
  445. X
  446. X
  447. XACKNOWLEDGEMENTS
  448. X================
  449. X
  450. XSpecial thanks to :
  451. X
  452. X Kris Croes                  croes@imec.be
  453. X
  454. XAnd the patchlevel 8 beta testers :
  455. X
  456. X Paul D. Smith               paul_smith@dg.com
  457. X Brian                       brian@natinst.com
  458. SHAR_EOF
  459. if test 4557 -ne "`wc -c < 'README'`"
  460. then
  461.     echo shar: error transmitting "'README'" '(should have been 4557 characters)'
  462. fi
  463. fi # end of overwriting check
  464. echo shar: extracting "'patchlevel.h'" '(22 characters)'
  465. if test -f 'patchlevel.h'
  466. then
  467.     echo shar: will not over-write existing file "'patchlevel.h'"
  468. else
  469. sed 's/^X//' << \SHAR_EOF > 'patchlevel.h'
  470. X#define PATCHLEVEL  8
  471. SHAR_EOF
  472. if test 22 -ne "`wc -c < 'patchlevel.h'`"
  473. then
  474.     echo shar: error transmitting "'patchlevel.h'" '(should have been 22 characters)'
  475. fi
  476. fi # end of overwriting check
  477. echo shar: extracting "'xautolock.c'" '(37774 characters)'
  478. if test -f 'xautolock.c'
  479. then
  480.     echo shar: will not over-write existing file "'xautolock.c'"
  481. else
  482. sed 's/^X//' << \SHAR_EOF > 'xautolock.c'
  483. X/***************************************************************************
  484. X *
  485. X * xautolock
  486. X * =========
  487. X *
  488. X * Authors   :  S. De Troch (SDT)
  489. X *              M. Eyckmans (MCE)
  490. X *
  491. X * Date      :  22/07/90
  492. X *
  493. X * Comments  :
  494. X *
  495. X * Review    :  - 12/02/92 (MCE) :
  496. X *                . Hacked around a dxcalendar problem.
  497. X *              - 21/02/92 (MCE) :
  498. X *                . Major rewrite.
  499. X *              - 24/02/92 (MCE) :
  500. X *                . Removed an initialization bug.
  501. X *              - 25/02/92 (MCE) :
  502. X *                . Added code to detect multiple invocations.
  503. X *              - 06/03/92 (MCE) :
  504. X *                . Re-arranged the event loop in order to detect defunct
  505. X *                  children as soon as possible.
  506. X *              - 10/03/92 (SDT & MCE) :
  507. X *                . Added code to detect broken server connections.
  508. X *              - 24/03/92 (MCE) :
  509. X *                . Don't reset the time-out counter after receiving a
  510. X *                  synthetic or otherwise unexpected event.
  511. X *              - 15/04/92 (MCE) :
  512. X *                . Changed the default locker to "xlock 2>&- 1>&-".
  513. X *                . Fixed a couple of event mask bugs. (Thanks to
  514. X *                  jwz@lucid.com for running into these.)
  515. X *                . Corrected a property type bug in CheckConnection ().
  516. X *              - 20/04/92 (MCE) :
  517. X *                . Cut Main () into more managable pieces.
  518. X *                . Periodically call XQueryPointer ().
  519. X *              - 25/04/92 (MCE) :
  520. X *                . Added the `corners' feature. (Suggested by
  521. X *                  weisen@alw.nih.gov.)
  522. X *                . Fixed a problem with pseudo-root windows. (Thanks to
  523. X *                  sherman@unx.sas.com, nedwards@titan.trl.OZ.AU,
  524. X *                  dave@elxr.jpl.Nasa.Gov and tmcconne@sedona.intel.com
  525. X *                  for pointing out the problem and testing the patch.)
  526. X *                . Added `disable/enable on SIGHUP'. (Suggested by
  527. X *                  paul_smith@dg.com.)
  528. X *                . Added support for multiheaded displays. 
  529. X *              - 28/04/92 (MCE) :
  530. X *                . Use the X resource manager.
  531. X *              - 06/05/92 (MCE) :
  532. X *                . Fixed a few potential portability problems. (Thanks
  533. X *                  to paul_smith@dg.com again.)
  534. X *                . CheckConnection () now works properly on multiheaded
  535. X *                  displays. (Thanks to brian@natinst.com for testing
  536. X *                  the `multiheaded' feature.)
  537. X *                . Better version of Sleep().
  538. X *                . Recognize X resources for class "Xautolock".
  539. X *                . Don't update timer while sighupped.
  540. X *                . Switched to vfork () and execl ().
  541. X *                . New copyright notice.
  542. X *              - 11/05/92 (MCE) :
  543. X *                . Close stdout and stderr in stead of using "2>&- 1>&-".
  544. X *                  (Suggested by sinkwitz@ifi.unizh.ch.)
  545. X *                . Added "-noclose" for debugging. 
  546. X *
  547. X * -------------------------------------------------------------------------
  548. X *
  549. X * Please send bug reports to detroch@imec.be or eyckmans@imec.be.
  550. X *
  551. X * -------------------------------------------------------------------------
  552. X *
  553. X * Copyright 1990, 1992 by S. De Troch and MCE.
  554. X *
  555. X * Permission to use, copy, modify and distribute this software and the
  556. X * supporting documentation without fee is hereby granted, provided that :
  557. X *
  558. X *  1 : Both the above copyright notice and this permission notice
  559. X *      appear in all copies of both the software and the supporting
  560. X *      documentation.
  561. X *  2 : You don't make a profit out of it.
  562. X *
  563. X * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  564. X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
  565. X * EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  566. X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
  567. X * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  568. X * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  569. X * PERFORMANCE OF THIS SOFTWARE.
  570. X *
  571. X ***************************************************************************/
  572. X
  573. X
  574. X
  575. X/*
  576. X *  Have a guess what this does...
  577. X *  ==============================
  578. X *
  579. X *  Warning for swm & tvtwm users : xautolock should *not* be compiled
  580. X *  with vroot.h, because it needs to know the real root window.
  581. X */
  582. X#include <stdio.h>
  583. X#include <strings.h>
  584. X#include <X11/Xlib.h>
  585. X#include <X11/Xatom.h>
  586. X#include <X11/Xresource.h>
  587. X#include <sys/types.h>
  588. X#include <sys/wait.h>
  589. X#include <signal.h>
  590. X#include <memory.h>
  591. X#include <math.h>
  592. X
  593. X#ifdef AIXV3    
  594. X#include <sys/m_wait.h>
  595. X#endif /* AIXV3 */
  596. X
  597. X#if !defined (news1800) && !defined (sun386)
  598. X
  599. X#include <stdlib.h>
  600. X
  601. X#ifndef apollo
  602. X#include <malloc.h>
  603. X#include <unistd.h>
  604. X#endif /* apollo */
  605. X
  606. X#endif /* !news1800 && !sun386 */
  607. X
  608. X#include "patchlevel.h"
  609. X
  610. X
  611. X
  612. X
  613. X/*
  614. X *  Usefull macros and customization stuff
  615. X *  ======================================
  616. X */
  617. X#ifdef HasPrototypes
  618. X#define PP(x)                      x
  619. X#else /* HasPrototypes */
  620. X#define PP(x)                      ()
  621. X#endif /* HasPrototypes */
  622. X
  623. X
  624. X#define FALSE                      0       /* as it says                   */
  625. X#define TRUE                       1       /* as it says                   */
  626. X
  627. X#define ALL_OK                     0       /* for use by exit ()           */
  628. X#define PROBLEMS                   1       /* for use by exit ()           */
  629. X#define BELL_PERCENT               40      /* as is says                   */
  630. X#define MIN_MINUTES                1       /* minimum number of minutes
  631. X                          before firing up the locker  */
  632. X#define MINUTES                    10      /* default ...                  */
  633. X#define MAX_MINUTES                60      /* maximum ...                  */
  634. X#define INITIAL_SLEEP              20      /* for machines on which the
  635. X                             login sequence takes forever */
  636. X#define INCREMENTAL_SLEEP          1       /* time step in seconds         */
  637. X#define CREATION_DELAY             30      /* should be > 10 and
  638. X                           < min (45,(MIN_MINUTES*30))  */
  639. X#define CORNER_SIZE                10      /* size in pixels of the
  640. X                            force-lock areas             */
  641. X#define CORNER_DELAY               5       /* number of seconds to wait
  642. X                          before forcing a lock        */
  643. X#define LOCKER                     "xlock" /* NEVER use the -root option!  */
  644. X#define CLASS                      "Xautolock"
  645. X                            /* as it says                   */
  646. X
  647. X#if SystemV == YES
  648. X#define vfork                      fork
  649. X#endif /* SystemV == YES */
  650. X
  651. X#define Main                       main
  652. X#define Min(a,b)                   (a < b ? a : b)
  653. X#define forever                    for (;;)
  654. X#define Output0(str)               (Void) fprintf (stdout, str)
  655. X#define Output1(str,arg1)          (Void) fprintf (stdout, str, arg1)
  656. X#define Output2(str,arg1,arg2)     (Void) fprintf (stdout, str, arg1, arg2)
  657. X#define Error0(str)                (Void) fprintf (stderr, str)
  658. X#define Error1(str,arg1)           (Void) fprintf (stderr, str, arg1)
  659. X#define Error2(str,arg1,arg2)      (Void) fprintf (stderr, str, arg1, arg2)
  660. X#define UpdateTimer(new_val)       if (!sighupped) timer = new_val
  661. X
  662. Xstatic void*                       ch_ptr;  /* this is dirty */
  663. X#define Skeleton(t,s)              (ch_ptr = (Void*) malloc ((unsigned) s), \
  664. X                       ch_ptr == (Void*) NULL                \
  665. X                       ?   (Error0 ("Out of memory.\n"),       \
  666. X                        (Void) exit (PROBLEMS),              \
  667. X                        (t*) NULL                            \
  668. X                       )                                     \
  669. X                        : (t*) ch_ptr                           \
  670. X                               )                                        \
  671. X
  672. X#define New(type)                  Skeleton (type, sizeof (type))
  673. X#define NewArray(type,nof_elems)   Skeleton (type, sizeof (type) * nof_elems)
  674. X
  675. X
  676. X
  677. X
  678. X/*
  679. X *  New types
  680. X *  =========
  681. X */
  682. X#if defined (apollo) || defined (news1800)
  683. Xtypedef int                        (*XErrorHandler) PP((Display*,
  684. X                               XErrorEvent*));
  685. X#endif /* apollo || news1800 */
  686. X
  687. X#if defined (news1800) || defined (sun386)
  688. Xtypedef int                        pid_t;
  689. X#endif /* news1800  || sun386 */
  690. X
  691. X#define Void                       void     /* no typedef because of VAX */
  692. Xtypedef int                        Int;
  693. Xtypedef char                       Char;
  694. Xtypedef char*                      String;
  695. Xtypedef int                        Boolean;
  696. Xtypedef caddr_t                    Caddrt;
  697. Xtypedef unsigned long              Huge;
  698. X
  699. X#ifdef HasVoidSignalReturn
  700. X#define SigRet                     Void     /* no typedef because of VAX */
  701. X#else /* HasVoidSignalReturn */
  702. Xtypedef Int                        SigRet;
  703. X#endif /* HasVoidSignalReturn */
  704. X
  705. Xtypedef SigRet                     (*SigHandler) PP((/* OS dependent */));
  706. Xtypedef Boolean                    (*OptAction)  PP((Display*, String,
  707. X                             String));
  708. Xtypedef Void                       (*OptChecker) PP((Display*));
  709. X
  710. Xtypedef enum
  711. X    {
  712. X      IGNORE,                                 /* ignore this corner  */
  713. X      DONT_LOCK,                              /* never lock          */
  714. X      FORCE_LOCK,                             /* lock immediately    */
  715. X    } CornerAction;
  716. X
  717. Xtypedef struct QueueItem_
  718. X    {
  719. X      Window                   window;        /* as it says          */
  720. X      Time                     creationtime;  /* as it says          */
  721. X      struct QueueItem_*       next;          /* as it says          */
  722. X      struct QueueItem_*       prev;          /* as it says          */
  723. X    } aQueueItem, *QueueItem;
  724. X
  725. Xtypedef struct Queue_
  726. X    {
  727. X      struct QueueItem_*       head;          /* as it says          */
  728. X      struct QueueItem_*       tail;          /* as it says          */
  729. X    } aQueue, *Queue;
  730. X
  731. Xtypedef struct Opt_
  732. X    {
  733. X      String                   name;          /* as it says          */
  734. X      XrmOptionKind            kind;          /* as it says          */
  735. X      Caddrt                   value;         /* XrmOptionNoArg only */
  736. X      OptAction                action;        /* as it says          */
  737. X      OptChecker               checker;       /* as it says          */
  738. X    } anOpt, *Opt;
  739. X
  740. X
  741. X
  742. X
  743. X/*
  744. X *  Function declarations
  745. X *  =====================
  746. X */
  747. X#ifdef news1800
  748. Xextern Void*    malloc             PP((unsigned int));
  749. X#endif /* news1800 */
  750. Xstatic Void     Usage              PP((String, Int));
  751. Xstatic Void     Sleep              PP((Void));
  752. Xstatic Void     EvaluateCounter    PP((Display*));
  753. Xstatic Void     QueryPointer       PP((Display*));
  754. Xstatic Void     ProcessEvents      PP((Display*, Queue));
  755. Xstatic Queue    NewQueue           PP((Void));
  756. Xstatic Void     AddToQueue         PP((Queue, Window));
  757. Xstatic Void     ProcessQueue       PP((Queue, Display*, Time));
  758. Xstatic Void     SelectEvents       PP((Display*, Window, Boolean));
  759. Xstatic Void     CheckConnection    PP((Display*, String));
  760. Xstatic Int      FetchFalseAlarm    PP((Display*, XEvent));
  761. Xstatic Void     ProcessOpts        PP((Display*, Int, String*));
  762. Xstatic Boolean  TimeAction         PP((Display*, String, String));
  763. Xstatic Boolean  LockerAction       PP((Display*, String, String));
  764. Xstatic Boolean  CornersAction      PP((Display*, String, String));
  765. Xstatic Boolean  CornerSizeAction   PP((Display*, String, String));
  766. Xstatic Boolean  CornerDelayAction  PP((Display*, String, String));
  767. Xstatic Boolean  NotifyAction       PP((Display*, String, String));
  768. Xstatic Boolean  BellAction         PP((Display*, String, String));
  769. Xstatic Boolean  NoCloseAction      PP((Display*, String, String));
  770. Xstatic Boolean  HelpAction         PP((Display*, String, String));
  771. Xstatic Boolean  VersionAction      PP((Display*, String, String));
  772. Xstatic Boolean  GetPositive        PP((String, Int*));
  773. Xstatic Void     TimeChecker        PP((Display*));
  774. Xstatic Void     NotifyChecker      PP((Display*));
  775. Xstatic Void     CornerSizeChecker  PP((Display*));
  776. Xstatic Void     BellChecker        PP((Display*));
  777. Xstatic SigRet   DisableBySignal    PP((Void));
  778. X
  779. X
  780. X
  781. X
  782. X/*
  783. X *  Global variables
  784. X *  ================
  785. X */
  786. Xstatic Time          now = 0;               /* number of sleeps since we
  787. X                               started (not `Int')        */
  788. Xstatic Int           timer = 0;             /* as it says (not `Time')    */
  789. Xstatic String        locker = LOCKER;       /* as it says                 */
  790. Xstatic Int           time_limit = MINUTES;  /* as it says (not `Time')    */
  791. Xstatic Int           notify_margin;         /* as it says (not `Time')    */
  792. Xstatic Int           bell_percent = BELL_PERCENT;
  793. X                        /* as it says                 */
  794. Xstatic Int           corner_size = CORNER_SIZE;
  795. X                        /* as it says                 */
  796. Xstatic Int           corner_delay = CORNER_DELAY;
  797. X                        /* as it says (not `Time')    */
  798. Xstatic Boolean       sighupped = FALSE;     /* whether to ignore all
  799. X                           time-outs                  */
  800. Xstatic Boolean       notify_lock = FALSE;   /* whether to notify the user
  801. X                               before locking             */
  802. Xstatic CornerAction  corners[4] = { IGNORE, IGNORE, IGNORE, IGNORE };
  803. X                                        /* default CornerActions      */
  804. Xstatic Boolean       close_output = TRUE;   /* whether to close stdout
  805. X                                               and stderr                 */
  806. Xstatic anOpt         options[] = 
  807. X                  {
  808. X                      {"help"       , XrmoptionNoArg   ,
  809. X                    (Caddrt) ""  , HelpAction       , (OptChecker) NULL},
  810. X                      {"version"    , XrmoptionNoArg   ,
  811. X                    (Caddrt) ""  , VersionAction    , (OptChecker) NULL},
  812. X                      {"locker"     , XrmoptionSepArg  ,
  813. X                    (Caddrt) NULL, LockerAction     , (OptChecker) NULL},
  814. X                      {"corners"    , XrmoptionSepArg  ,
  815. X                    (Caddrt) NULL, CornersAction    , (OptChecker) NULL},
  816. X                      {"cornersize" , XrmoptionSepArg  ,
  817. X                    (Caddrt) NULL, CornerSizeAction , CornerSizeChecker},
  818. X                      {"cornerdelay", XrmoptionSepArg  ,
  819. X                    (Caddrt) NULL, CornerDelayAction, (OptChecker) NULL},
  820. X                      {"time"       , XrmoptionSepArg  ,
  821. X                    (Caddrt) NULL, TimeAction       , TimeChecker      },
  822. X                      {"notify"     , XrmoptionSepArg  ,
  823. X                    (Caddrt) NULL, NotifyAction     , NotifyChecker    },
  824. X                      {"bell"       , XrmoptionSepArg  ,
  825. X                    (Caddrt) NULL, BellAction       , BellChecker      },
  826. X                      {"noclose"    , XrmoptionNoArg   ,
  827. X                    (Caddrt) ""  , NoCloseAction    , (OptChecker) NULL},
  828. X                  };                     /* as it says, the order is
  829. X                           important                  */
  830. X
  831. X
  832. X
  833. X
  834. X/*
  835. X *  Command line argument related functions
  836. X *  =======================================
  837. X *
  838. X *  Support functions
  839. X *  -----------------
  840. X */
  841. Xstatic Boolean  GetPositive (arg, pos)
  842. XString  arg;  /* string to scan                  */
  843. XInt*    pos;  /* adress where to store the stuff */
  844. X
  845. X{
  846. X  Char  c;           /* dummy            */
  847. X  Int   old = *pos;  /* backup old value */
  848. X
  849. X
  850. X  if (   sscanf (arg, "%d%c", pos, &c) == 1
  851. X      && *pos >= 0
  852. X     )
  853. X  {
  854. X    return TRUE;
  855. X  }
  856. X  else
  857. X  {
  858. X    *pos = old;
  859. X    return FALSE;
  860. X  }
  861. X}
  862. X
  863. X
  864. X
  865. X/*
  866. X *  Action functions
  867. X *  ----------------
  868. X */
  869. X/*ARGSUSED*/
  870. Xstatic Boolean  HelpAction (d, name, arg)
  871. XDisplay*  d;     /* display pointer */
  872. XString    name;  /* program name    */
  873. XString    arg;   /* argument value  */
  874. X
  875. X{
  876. X  Usage (name, ALL_OK);
  877. X
  878. X  return TRUE;  /* for lint and gcc */
  879. X}
  880. X
  881. X
  882. X/*ARGSUSED*/
  883. Xstatic Boolean  VersionAction (d, name, arg)
  884. XDisplay*  d;     /* display pointer */
  885. XString    name;  /* program name    */
  886. XString    arg;   /* argument value  */
  887. X
  888. X{
  889. X  Error2 ("%s : patchlevel %d\n", name, PATCHLEVEL);
  890. X  (Void) exit (ALL_OK);
  891. X
  892. X  return TRUE;  /* for lint and gcc */
  893. X}
  894. X
  895. X
  896. X/*ARGSUSED*/
  897. Xstatic Boolean  CornerSizeAction (d, name, arg)
  898. XDisplay*  d;     /* display pointer */
  899. XString    name;  /* program name    */
  900. XString    arg;   /* argument value  */
  901. X
  902. X{
  903. X  return GetPositive (arg, &corner_size);
  904. X}
  905. X
  906. X
  907. X/*ARGSUSED*/
  908. Xstatic Boolean  CornerDelayAction (d, name, arg)
  909. XDisplay*  d;     /* display pointer */
  910. XString    name;  /* program name    */
  911. XString    arg;   /* argument value  */
  912. X
  913. X{
  914. X  return GetPositive (arg, &corner_delay);
  915. X}
  916. X
  917. X
  918. X/*ARGSUSED*/
  919. Xstatic Boolean  TimeAction (d, name, arg)
  920. XDisplay*  d;     /* display pointer */
  921. XString    name;  /* program name    */
  922. XString    arg;   /* argument value  */
  923. X
  924. X{
  925. X  return GetPositive (arg, &time_limit);
  926. X}
  927. X
  928. X
  929. X/*ARGSUSED*/
  930. Xstatic Boolean  NotifyAction (d, name, arg)
  931. XDisplay*  d;     /* display pointer */
  932. XString    name;  /* program name    */
  933. XString    arg;   /* argument value  */
  934. X
  935. X{
  936. X  return notify_lock = GetPositive (arg, ¬ify_margin);
  937. X}
  938. X
  939. X
  940. X/*ARGSUSED*/
  941. Xstatic Boolean  BellAction (d, name, arg)
  942. XDisplay*  d;     /* display pointer */
  943. XString    name;  /* program name    */
  944. XString    arg;   /* argument value  */
  945. X
  946. X{
  947. X  return GetPositive (arg, &bell_percent);
  948. X}
  949. X
  950. X
  951. X/*ARGSUSED*/
  952. Xstatic Boolean  NoCloseAction (d, name, arg)
  953. XDisplay*  d;     /* display pointer */
  954. XString    name;  /* program name    */
  955. XString    arg;   /* argument value  */
  956. X
  957. X{
  958. X  close_output = FALSE;
  959. X  return TRUE;
  960. X}
  961. X
  962. X
  963. X/*ARGSUSED*/
  964. Xstatic Boolean  LockerAction (d, name, arg)
  965. XDisplay*  d;     /* display pointer */
  966. XString    name;  /* program name    */
  967. XString    arg;   /* argument value  */
  968. X
  969. X{
  970. X  locker = arg;
  971. X  return TRUE;
  972. X}
  973. X
  974. X
  975. X/*ARGSUSED*/
  976. Xstatic Boolean  CornersAction (d, name, arg)
  977. XDisplay*  d;     /* display pointer */
  978. XString    name;  /* program name    */
  979. XString    arg;   /* argument value  */
  980. X
  981. X{
  982. X  Int  c;  /* loop counter */
  983. X
  984. X
  985. X  if (strlen (arg) == 4)
  986. X  {
  987. X    for (c = -1; ++c < 4; )
  988. X    {
  989. X      switch (arg[c])
  990. X      {
  991. X    case '0' :
  992. X      corners[c] = IGNORE;
  993. X      continue;
  994. X
  995. X    case '-' :
  996. X      corners[c] = DONT_LOCK;
  997. X      continue;
  998. X
  999. X    case '+' :
  1000. X      corners[c] = FORCE_LOCK;
  1001. X      continue;
  1002. X
  1003. X    default :
  1004. X      return FALSE;
  1005. X      }
  1006. X    }
  1007. X
  1008. X    return TRUE;
  1009. X  }
  1010. X  else
  1011. X  {
  1012. X    return FALSE;
  1013. X  }
  1014. X}
  1015. X
  1016. X
  1017. X
  1018. X/*
  1019. X *  Consistency checkers
  1020. X *  --------------------
  1021. X */
  1022. X/*ARGSUSED*/
  1023. Xstatic Void  TimeChecker (d)
  1024. XDisplay*  d;  /* display pointer */
  1025. X
  1026. X{
  1027. X  if (time_limit < MIN_MINUTES)
  1028. X  {
  1029. X    Error1 ("Setting time to minimum value of %d minute(s).\n",
  1030. X            time_limit = MIN_MINUTES);
  1031. X  }
  1032. X  else if (time_limit > MAX_MINUTES)
  1033. X  {
  1034. X    Error1 ("Setting time to maximum value of %d minute(s).\n",
  1035. X            time_limit = MAX_MINUTES);
  1036. X  }
  1037. X
  1038. X  time_limit *= 60; /* convert to seconds */
  1039. X}
  1040. X
  1041. X
  1042. X/*ARGSUSED*/
  1043. Xstatic Void  NotifyChecker (d)
  1044. XDisplay*  d;  /* display pointer */
  1045. X
  1046. X{
  1047. X  if (   notify_lock
  1048. X      && notify_margin >= time_limit / 2
  1049. X     )
  1050. X  {
  1051. X    Error1 ("Notification time set to %d seconds.\n",
  1052. X            notify_margin = time_limit / 2);
  1053. X  }
  1054. X}
  1055. X
  1056. X
  1057. X/*ARGSUSED*/
  1058. Xstatic Void  BellChecker (d)
  1059. XDisplay*  d;  /* display pointer */
  1060. X
  1061. X{
  1062. X  if (   bell_percent < 1
  1063. X      || bell_percent > 100
  1064. X     )
  1065. X  {
  1066. X    Error1 ("Bell percentage set to %d%%.\n",
  1067. X        bell_percent = BELL_PERCENT);
  1068. X  }
  1069. X}
  1070. X
  1071. X
  1072. X/*ARGSUSED*/
  1073. Xstatic Void  CornerSizeChecker (d)
  1074. XDisplay*  d;  /* display pointer */
  1075. X
  1076. X{
  1077. X  Int      s;                /* screen index   */
  1078. X  Screen*  scr;              /* screen pointer */
  1079. X  Int      max_corner_size;  /* as it says     */
  1080. X  
  1081. X
  1082. X  for (max_corner_size = 32000, s = -1; ++s < ScreenCount (d); )
  1083. X  {
  1084. X    scr = ScreenOfDisplay (d, s);
  1085. X
  1086. X    if (   max_corner_size > WidthOfScreen (scr) / 4
  1087. X    || max_corner_size > HeightOfScreen (scr) / 4
  1088. X       )
  1089. X    {
  1090. X      max_corner_size = Min (WidthOfScreen (scr), HeightOfScreen (scr)) / 4;
  1091. X    }
  1092. X  }
  1093. X
  1094. X  if (corner_size > max_corner_size)
  1095. X  {
  1096. X    Error1 ("Corner size set to %d pixels.\n",
  1097. X        corner_size = max_corner_size);
  1098. X  }
  1099. X}
  1100. X
  1101. X
  1102. X
  1103. X/*
  1104. X *  Function for informing the user about syntax errors
  1105. X *  ---------------------------------------------------
  1106. X */
  1107. Xstatic Void  Usage (prog_name, exit_code)
  1108. XString  prog_name;  /* as it says */
  1109. XInt     exit_code;  /* as it says */
  1110. X
  1111. X{
  1112. X  String  blanks;  /* string full of blanks */
  1113. X  size_t  len;     /* number of blanks      */
  1114. X
  1115. X
  1116. X /*
  1117. X  *  The relative overhead is enormous here, but who cares.
  1118. X  *  I'm a perfectionist and Usage () doesn't return anyway.
  1119. X  */
  1120. X  len = strlen ("Usage : ") + strlen (prog_name) + 1;
  1121. X  (Void) memset (blanks = NewArray (Char, len + 1), ' ', len);
  1122. X  blanks[len] = '\0';
  1123. X
  1124. X
  1125. X /*
  1126. X  *  This is where the actual work gets done...
  1127. X  */
  1128. X  Error0 ("\n");
  1129. X  Error1 ("Usage : %s ", prog_name);
  1130. X  Error0 ("[-help][-version][-time minutes][-locker locker]\n");
  1131. X  Error0 (blanks);
  1132. X  Error0 ("[-notify margin][-bell percent][-corners xxxx]\n");
  1133. X  Error0 (blanks);
  1134. X  Error0 ("[-cornerdelay secs][-cornersize pixels][-noclose]\n");
  1135. X
  1136. X  Error0 ("\n");
  1137. X  Error0 (" -help              : print this message and exit.\n");
  1138. X  Error0 (" -version           : print version number and exit.\n");
  1139. X  Error2 (" -time minutes      : time to lock screen [%d < minutes < %d].\n",
  1140. X                             MIN_MINUTES, MAX_MINUTES);
  1141. X  Error0 (" -locker locker     : program used to lock.\n");
  1142. X  Error0 (" -notify margin     : beep this many seconds before locking.\n");
  1143. X  Error0 (" -bell percent      : loudness of the beep.\n");
  1144. X  Error0 (" -corners xxxx      : corner actions (0, +, -) in this order :\n");
  1145. X  Error0 ("                      topleft topright bottomleft bottomright\n");
  1146. X  Error0 (" -cornerdelay secs  : time to lock screen in a `+' corner.\n");
  1147. X  Error0 (" -cornersize pixels : size of corner areas.\n");
  1148. X  Error0 (" -noclose           : do not close stdout and stderr.\n");
  1149. X
  1150. X  Error0 ("\n");
  1151. X  Error0 ("Defaults :\n");
  1152. X
  1153. X  Error0 ("\n");
  1154. X  Error1 ("  time        : %d minutes\n"  , MINUTES     );
  1155. X  Error1 ("  locker      : %s\n"          , LOCKER      );
  1156. X  Error0 ("  notify      : don't beep\n"                );
  1157. X  Error0 ("  bell        : 40%%\n"                      );
  1158. X  Error0 ("  corners     : 0000\n"                      );
  1159. X  Error1 ("  cornerdelay : %d seconds\n"  , CORNER_DELAY);
  1160. X  Error1 ("  cornersize  : %d pixels\n"   , CORNER_SIZE );
  1161. X
  1162. X  Error0 ("\n");
  1163. X
  1164. X  exit (exit_code);
  1165. X}
  1166. X
  1167. X
  1168. X
  1169. X/*
  1170. X *  Function for processing command line arguments
  1171. X *  ----------------------------------------------
  1172. X */
  1173. Xstatic Void  ProcessOpts (d, argc, argv)
  1174. XDisplay*  d;       /* display pointer     */
  1175. XInt       argc;    /* number of arguments */
  1176. XString    argv[];  /* array of arguments  */
  1177. X
  1178. X{
  1179. X  Int                nof_options = sizeof (options) / sizeof (anOpt);
  1180. X                              /* number of supported options   */
  1181. X  Int                j;           /* loop counter                  */
  1182. X  Int                l;           /* temporary storage             */
  1183. X  Char*              ptr;         /* temporary storage             */
  1184. X  Char               buffer[80];  /* as it says                    */
  1185. X  Char*              dummy;       /* as it says                    */
  1186. X  XrmValue           value;       /* resource value container      */
  1187. X  XrmOptionDescList  xoptions;    /* optionslist in Xlib format    */
  1188. X  XrmDatabase        db = (XrmDatabase) NULL;
  1189. X                  /* command line options database */
  1190. X
  1191. X
  1192. X /*
  1193. X  *  Beautify argv[0].
  1194. X  */
  1195. X  for (ptr = argv[0] + strlen (argv[0]) - 1; ptr >= argv[0]; ptr--)
  1196. X  {
  1197. X    if (*ptr == '/')
  1198. X    {
  1199. X      break;
  1200. X    }
  1201. X  }
  1202. X
  1203. X  argv[0] = ptr + 1;
  1204. X
  1205. X
  1206. X /*
  1207. X  *  Calling XGetDefault () on a dummy resource is the easiest 
  1208. X  *  way to get both Xrm and d->db initialized.
  1209. X  */
  1210. X  (Void) XGetDefault (d, argv[0], "dummy");
  1211. X
  1212. X
  1213. X /*
  1214. X  *  Parse the command line options into a resource database. (The
  1215. X  *  command line database and the resource file database are not
  1216. X  *  merged, because we want to know where exactly each resource
  1217. X  *  value came from.)
  1218. X  */
  1219. X  xoptions = NewArray (XrmOptionDescRec, nof_options);
  1220. X
  1221. X  for (j = -1; ++j < nof_options; )
  1222. X  {
  1223. X    l = strlen (options[j].name);
  1224. X
  1225. X    (Void) sprintf (xoptions[j].option = NewArray (Char, l + 2),
  1226. X                "-%s", options[j].name);
  1227. X    (Void) sprintf (xoptions[j].specifier = NewArray (Char, l + 2),
  1228. X                ".%s", options[j].name);
  1229. X    xoptions[j].argKind = options[j].kind;
  1230. X    xoptions[j].value = options[j].value;
  1231. X  }
  1232. X
  1233. X  XrmParseCommand (&db, xoptions, nof_options, argv[0], &argc, argv);
  1234. X
  1235. X  if (--argc)
  1236. X  {
  1237. X    Usage (argv[0], PROBLEMS);
  1238. X  }
  1239. X
  1240. X  for (j = -1; ++j < nof_options; )
  1241. X  {
  1242. X    free (xoptions[j].option);
  1243. X    free (xoptions[j].specifier);
  1244. X  }
  1245. X
  1246. X  free (xoptions);
  1247. X
  1248. X
  1249. X /*
  1250. X  *  Call the action functions.
  1251. X  */
  1252. X  for (j = -1; ++j < nof_options; )
  1253. X  {
  1254. X    (Void) sprintf (buffer, "%s%s", argv[0], xoptions[j].specifier);
  1255. X
  1256. X    if (XrmGetResource (db, buffer, (String) NULL, &dummy, &value))
  1257. X    {
  1258. X      if (!(*(options[j].action)) (d, argv[0], value.addr))
  1259. X      {
  1260. X        Usage (argv[0], PROBLEMS); 
  1261. X      }
  1262. X    }
  1263. X    else if (XrmGetResource (d->db, buffer, (String) NULL, &dummy, &value))
  1264. X    {
  1265. X      if (!(*(options[j].action)) (d, argv[0], value.addr))
  1266. X      {
  1267. X        Error2 ("Can't interprete \"%s\" for \"%s\", using default.\n", 
  1268. X            value.addr, buffer);
  1269. X      }
  1270. X    }
  1271. X    else
  1272. X    {
  1273. X      (Void) sprintf (buffer, "%s%s", CLASS, xoptions[j].specifier);
  1274. X
  1275. X      if (   XrmGetResource (d->db, buffer, (String) NULL, &dummy, &value)
  1276. X          && !(*(options[j].action)) (d, argv[0], value.addr)
  1277. X         )
  1278. X      {
  1279. X        Error2 ("Can't interprete \"%s\" for \"%s\", using default.\n", 
  1280. X            value.addr, buffer);
  1281. X      }
  1282. X    }
  1283. X  }
  1284. X
  1285. X
  1286. X
  1287. X /*
  1288. X  *  Call the consistency checkers.
  1289. X  */
  1290. X  for (j = -1; ++j < nof_options; )
  1291. X  {
  1292. X    if (options[j].checker != (OptChecker) NULL)
  1293. X    {
  1294. X      (*(options[j].checker)) (d);
  1295. X    }
  1296. X  }
  1297. X}
  1298. X
  1299. X
  1300. X
  1301. X
  1302. X/*
  1303. X *  Functions related to the window queue
  1304. X *  =====================================
  1305. X *
  1306. X *  Function for creating a new queue
  1307. X *  ---------------------------------
  1308. X */
  1309. Xstatic Queue  NewQueue ()
  1310. X
  1311. X{
  1312. X  Queue  queue;  /* return value */
  1313. X
  1314. X
  1315. X  queue = New (aQueue);
  1316. X  queue->tail = New (aQueueItem);
  1317. X  queue->head = New (aQueueItem);
  1318. X
  1319. X  queue->tail->next = queue->head;
  1320. X  queue->head->prev = queue->tail;
  1321. X  queue->tail->prev = queue->head->next = (QueueItem) NULL;
  1322. X
  1323. X  return queue;
  1324. X}
  1325. X
  1326. X
  1327. X
  1328. X/*
  1329. X *  Function for adding an item to a queue
  1330. X *  --------------------------------------
  1331. X */
  1332. Xstatic Void  AddToQueue (queue, window)
  1333. XQueue   queue;   /* as it says */
  1334. XWindow  window;  /* as it says */
  1335. X
  1336. X{
  1337. X  QueueItem  new;  /* new item */
  1338. X
  1339. X
  1340. X  new = New (aQueueItem);
  1341. X
  1342. X  new->window = window;
  1343. X  new->creationtime = now;
  1344. X  new->next = queue->tail->next;
  1345. X  new->prev = queue->tail;
  1346. X  queue->tail->next->prev = new;
  1347. X  queue->tail->next = new;
  1348. X}
  1349. X
  1350. X
  1351. X
  1352. X/*
  1353. X *  Function for processing those entries that are old enough
  1354. X *  ---------------------------------------------------------
  1355. X */
  1356. Xstatic Void  ProcessQueue (queue, d, age)
  1357. XQueue     queue;  /* as it says      */
  1358. XDisplay*  d;      /* display pointer */
  1359. XTime      age;    /* required age    */
  1360. X
  1361. X{
  1362. X  QueueItem  current;  /* as it says */
  1363. X
  1364. X
  1365. X  if (now > age)
  1366. X  {
  1367. X    current = queue->head->prev;
  1368. X
  1369. X    while (   current->prev
  1370. X       && current->creationtime + age < now
  1371. X      )
  1372. X    {
  1373. X      SelectEvents (d, current->window, False);
  1374. X      current = current->prev;
  1375. X      free (current->next);
  1376. X    }
  1377. X
  1378. X    current->next = queue->head;
  1379. X    queue->head->prev = current;
  1380. X  }
  1381. X}
  1382. X
  1383. X
  1384. X
  1385. X
  1386. X/*
  1387. X *  Functions related to (the lack of) user activity
  1388. X *  ================================================
  1389. X *
  1390. X *  Function for processing the event queue
  1391. X *  ---------------------------------------
  1392. X */
  1393. Xstatic Void  ProcessEvents (d, queue)
  1394. XDisplay*  d;      /* display pointer */
  1395. XQueue     queue;  /* as it says      */
  1396. X
  1397. X{
  1398. X  XEvent  event;  /* as it says */
  1399. X
  1400. X
  1401. X /*
  1402. X  *  Read whatever is available for reading.
  1403. X  */
  1404. X  while (XPending (d))
  1405. X  {
  1406. X    if (XCheckMaskEvent (d, SubstructureNotifyMask, &event))
  1407. X    {
  1408. X      if (event.type == CreateNotify)
  1409. X      {
  1410. X    AddToQueue (queue, event.xcreatewindow.window);
  1411. X      }
  1412. X    }
  1413. X    else
  1414. X    {
  1415. X      XNextEvent (d, &event);
  1416. X    }
  1417. X
  1418. X
  1419. X   /*
  1420. X    *  Reset the counter if and only if the event is of one of
  1421. X    *  the types we are expecting to get *and* was not generated by
  1422. X    *  XSendEvent ().
  1423. X    */
  1424. X    if (   event.type == KeyPress
  1425. X    && !event.xany.send_event
  1426. X       )
  1427. X    {
  1428. X      UpdateTimer (0);
  1429. X    }
  1430. X  }
  1431. X
  1432. X
  1433. X /*
  1434. X  *  Check the window queue for entries that are older than
  1435. X  *  CREATION_DELAY seconds.
  1436. X  */
  1437. X  ProcessQueue (queue, d, (Time) CREATION_DELAY);
  1438. X}
  1439. X
  1440. X
  1441. X
  1442. X/*
  1443. X *  Function for monitoring pointer movements
  1444. X *  -----------------------------------------
  1445. X */
  1446. Xstatic Void  QueryPointer (d)
  1447. XDisplay*  d;  /* display pointer */
  1448. X
  1449. X{
  1450. X  Window          dummy_w;            /* as it says                    */
  1451. X  Int             dummy_c;            /* as it says                    */
  1452. X  Mask            dummy_m;            /* as it says                    */
  1453. X  Int             root_x;             /* as it says                    */
  1454. X  Int             root_y;             /* as it says                    */
  1455. X  Int             corner;             /* corner index                  */
  1456. X  Int             i;                  /* loop counter                  */
  1457. X  static Window   root;               /* root window the pointer is on */
  1458. X  static Screen*  screen;             /* screen the pointer is on      */
  1459. X  static Int      prev_root_x = -1;   /* as it says                    */
  1460. X  static Int      prev_root_y = -1;   /* as it says                    */
  1461. X  static Boolean  first_call = TRUE;  /* as it says                    */
  1462. X
  1463. X
  1464. X /*
  1465. X  *  Have a guess...
  1466. X  */
  1467. X  if (first_call)
  1468. X  {
  1469. X    first_call = FALSE;
  1470. X    root = DefaultRootWindow (d);
  1471. X    screen = ScreenOfDisplay (d, DefaultScreen (d));
  1472. X  }
  1473. X
  1474. X
  1475. X /*
  1476. X  *  Find out whether the pointer has moved. Using XQueryPointer for this
  1477. X  *  is gross, but it also is the only way never to mess up propagation
  1478. X  *  of pointer events.
  1479. X  *
  1480. X  *  Remark : Unlike XNextEvent(), XPending () doesn't notice if the
  1481. X  *           connection to the server is lost. For this reason, earlier
  1482. X  *           versions of xautolock periodically called XNoOp (). But
  1483. X  *           why not let XQueryPointer () do the job for us, since
  1484. X  *           we now call it every INCREMENTAL_SLEEP seconds anyway?
  1485. X  */
  1486. X  if (!XQueryPointer (d, root, &root, &dummy_w, &root_x, &root_y,
  1487. X              &dummy_c, &dummy_c, &dummy_m))
  1488. X  {
  1489. X   /*
  1490. X    *  Pointer has moved to another screen, so let's find out which one.
  1491. X    */
  1492. X    for (i = -1; ++i < ScreenCount (d); ) 
  1493. X    {
  1494. X      if (root == RootWindow (d, i)) 
  1495. X      {
  1496. X        screen = ScreenOfDisplay (d, i);
  1497. X    break;
  1498. X      }
  1499. X    }
  1500. X  }
  1501. X
  1502. X  if (   root_x == prev_root_x
  1503. X      && root_y == prev_root_y
  1504. X     )
  1505. X  {
  1506. X   /*
  1507. X    *  If the pointer has not moved since the previous call and 
  1508. X    *  is inside one of the 4 corners, we act according to the
  1509. X    *  contents of the "corners" array.
  1510. X    */
  1511. X    if (   (corner = 0,
  1512. X           root_x <= corner_size
  1513. X        && root_y <= corner_size
  1514. X       )
  1515. X    || (corner++,
  1516. X           root_x >= WidthOfScreen  (screen) - corner_size - 1
  1517. X        && root_y <= corner_size
  1518. X       )
  1519. X    || (corner++,
  1520. X           root_x <= corner_size
  1521. X        && root_y >= HeightOfScreen (screen) - corner_size - 1
  1522. X       )
  1523. X    || (corner++,
  1524. X           root_x >= WidthOfScreen  (screen) - corner_size - 1
  1525. X        && root_y >= HeightOfScreen (screen) - corner_size - 1
  1526. X       )
  1527. X       )
  1528. X    {
  1529. X      switch (corners[corner])
  1530. X      {
  1531. X    case FORCE_LOCK :
  1532. X      if (timer < time_limit - corner_delay + 2)
  1533. X      {
  1534. X        UpdateTimer (time_limit - corner_delay + 2);
  1535. X      }
  1536. X      break;
  1537. X
  1538. X    case DONT_LOCK :
  1539. X      UpdateTimer (0);
  1540. X      }
  1541. X    }
  1542. X  }
  1543. X  else
  1544. X  {
  1545. X    prev_root_x = root_x;
  1546. X    prev_root_y = root_y;
  1547. X    UpdateTimer (0);
  1548. X  }
  1549. X}
  1550. X
  1551. X
  1552. X
  1553. X/*
  1554. X *  Function for deciding whether to lock
  1555. X *  -------------------------------------
  1556. X */
  1557. Xstatic Void  EvaluateCounter (d)
  1558. XDisplay*  d;  /* display pointer */
  1559. X
  1560. X{
  1561. X  static pid_t  locker_pid = 0;  /* child pid  */
  1562. X  static Time   prev_bell = 0;   /* as it says */
  1563. X
  1564. X
  1565. X /*
  1566. X  *  Find out whether we should do something special. This can
  1567. X  *  be one (or more) of the following :
  1568. X  *
  1569. X  *   - Wait for the previous locker (if any).
  1570. X  *   - Ring the bell, if we were asked to and are about to lock.
  1571. X  *   - Start up a new locker if the time limit has been reached.
  1572. X  */
  1573. X  if (locker_pid)
  1574. X  {
  1575. X    union wait  status;  /* childs process status */
  1576. X
  1577. X
  1578. X    if (!wait3 (&status, WNOHANG, (struct rusage*) NULL))
  1579. X    {
  1580. X      UpdateTimer (0);
  1581. X    }
  1582. X    else
  1583. X    {
  1584. X      locker_pid = 0;
  1585. X    }
  1586. X  }
  1587. X
  1588. X  if (   notify_lock
  1589. X      && timer + notify_margin > time_limit
  1590. X      && prev_bell < now - notify_margin - 1
  1591. X     )
  1592. X  {
  1593. X    prev_bell = now;
  1594. X    XBell (d, bell_percent);
  1595. X    XSync (d, 0);
  1596. X  }
  1597. X
  1598. X  if (timer > time_limit)
  1599. X  {
  1600. X    if (!locker_pid)
  1601. X    {
  1602. X      switch (locker_pid = vfork ())
  1603. X      {
  1604. X    case -1 :
  1605. X      locker_pid = 0;
  1606. X      break;
  1607. X
  1608. X    case 0 :
  1609. X      (Void) close (ConnectionNumber (d));
  1610. X      (Void) execl ("/bin/sh", "sh", "-c", locker, (String) NULL);
  1611. X      (Void) _exit (PROBLEMS);
  1612. X
  1613. X    default :
  1614. X      UpdateTimer (0);
  1615. X      }
  1616. X    }
  1617. X  }
  1618. X}
  1619. X
  1620. X
  1621. X
  1622. X
  1623. X/*
  1624. X *  Miscellaneous functions
  1625. X *  =======================
  1626. X *
  1627. X *  X Error handler
  1628. X *  ---------------
  1629. X */
  1630. X/*ARGSUSED*/
  1631. Xstatic Int  FetchFalseAlarm (d, event)
  1632. XDisplay*  d;      /* display pointer */
  1633. XXEvent    event;  /* error event     */
  1634. X
  1635. X{
  1636. X  return 0;
  1637. X}
  1638. X
  1639. X
  1640. X
  1641. X/*
  1642. X *  SIGHUP signal handler
  1643. X *  ---------------------
  1644. X */
  1645. Xstatic SigRet  DisableBySignal ()
  1646. X
  1647. X{
  1648. X /*
  1649. X  *  The order in which things are done is rather important here.
  1650. X  */
  1651. X  UpdateTimer (0);
  1652. X  sighupped = !sighupped;
  1653. X  (Void) signal (SIGHUP, (SigHandler) DisableBySignal);
  1654. X
  1655. X#ifndef HasVoidSignalReturn 
  1656. X  return 0;
  1657. X#endif /* HasVoidSignalReturn */
  1658. X}
  1659. X
  1660. X
  1661. X
  1662. X/*
  1663. X *  Lazy function
  1664. X *  -------------
  1665. X */
  1666. Xstatic Void  Sleep ()
  1667. X
  1668. X{
  1669. X  Int  i;  /* loop counter */
  1670. X
  1671. X
  1672. X  for (i = -1; ++i < INCREMENTAL_SLEEP; )
  1673. X  {
  1674. X    (Void) sleep (1);
  1675. X    UpdateTimer (timer + 1);
  1676. X    now++;
  1677. X  }
  1678. X}
  1679. X
  1680. X
  1681. X
  1682. X/*
  1683. X *  Function for finding out whether another xautolock is already running
  1684. X *  ---------------------------------------------------------------------
  1685. X */
  1686. Xstatic Void  CheckConnection (d, prog_name)
  1687. XDisplay*  d;          /* display pointer */
  1688. XString    prog_name;  /* as it says      */
  1689. X
  1690. X{
  1691. X  pid_t   pid;        /* as it says              */
  1692. X  Int     kill_val;   /* return value of kill () */
  1693. X  Window  r;          /* root window             */
  1694. X  Atom    property;   /* property atom           */
  1695. X  Atom    type;       /* property type atom      */
  1696. X  Int     format;     /* property format         */
  1697. X  Huge    nof_items;  /* actual number of items  */
  1698. X  Huge    after;      /* dummy                   */
  1699. X  pid_t*  contents;   /* actual property value   */
  1700. X
  1701. X
  1702. X  r = RootWindowOfScreen (ScreenOfDisplay (d, 0));
  1703. X  property = XInternAtom (d, "XAUTOLOCK_SEMAPHORE_PID", False);
  1704. X
  1705. X  XGrabServer (d);
  1706. X  XGetWindowProperty (d, r, property, 0L, 2L, False, AnyPropertyType,
  1707. X              &type, &format, &nof_items, &after,
  1708. X              (unsigned char**) &contents);
  1709. X
  1710. X  if (type == XA_INTEGER)
  1711. X  {
  1712. X   /*
  1713. X    *  This breaks if the other xautolock is not 
  1714. X    *  running on the same machine.
  1715. X    */
  1716. X    kill_val = kill (*contents, 0);
  1717. X
  1718. X    if (kill_val == 0)
  1719. X    {
  1720. X      Error2 ("%s is already running (PID %d).\n",
  1721. X          prog_name, *contents);
  1722. X      (Void) exit (PROBLEMS);
  1723. X    }
  1724. X  }
  1725. X
  1726. X  pid = getpid ();
  1727. X  XChangeProperty (d, r, property, XA_INTEGER, 8,
  1728. X               PropModeReplace, (Char*) &pid, sizeof (pid));
  1729. X  XUngrabServer (d);
  1730. X
  1731. X  XFree ((Char*) contents);
  1732. X}
  1733. X
  1734. X
  1735. X
  1736. X/*
  1737. X *  Function for selecting events on a tree of windows
  1738. X *  --------------------------------------------------
  1739. X */
  1740. Xstatic Void  SelectEvents (d, window, substructure_only)
  1741. XDisplay*  d;                  /* display pointer   */
  1742. XWindow    window;             /* window            */
  1743. XBoolean   substructure_only;  /* as it says        */
  1744. X
  1745. X{
  1746. X  Window             root;              /* root window of this window */
  1747. X  Window             parent;            /* parent of this window      */
  1748. X  Window*            children;          /* children of this window    */
  1749. X  Int                nof_children = 0;  /* number of children         */
  1750. X  Int                i;                 /* loop counter               */
  1751. X  XWindowAttributes  attribs;           /* attributes of the window   */
  1752. X
  1753. X
  1754. X /*
  1755. X  *  Start by querying the server about parent and child windows.
  1756. X  */
  1757. X  if (!XQueryTree (d, window, &root, &parent, &children, &nof_children))
  1758. X  {
  1759. X    return;
  1760. X  }
  1761. X
  1762. X
  1763. X /*
  1764. X  *  Build the appropriate event mask. The basic idea is that we don't
  1765. X  *  want to interfere with the normal event propagation mechanism if
  1766. X  *  we don't have to.
  1767. X  */
  1768. X  if (substructure_only)
  1769. X  {
  1770. X    XSelectInput (d, window, SubstructureNotifyMask);
  1771. X  }
  1772. X  else
  1773. X  {
  1774. X    if (parent == None)  /* the *real* rootwindow */
  1775. X    {
  1776. X      attribs.all_event_masks = 
  1777. X      attribs.do_not_propagate_mask = KeyPressMask;
  1778. X    }
  1779. X    else if (XGetWindowAttributes (d, window, &attribs) == 0)
  1780. X    {
  1781. X      return;
  1782. X    }
  1783. X
  1784. X    XSelectInput (d, window,   SubstructureNotifyMask
  1785. X                     | (  (  attribs.all_event_masks
  1786. X                   | attribs.do_not_propagate_mask)
  1787. X                & KeyPressMask));
  1788. X  }
  1789. X
  1790. X
  1791. X /*
  1792. X  *  Now do the same thing for all children.
  1793. X  */
  1794. X  for (i = -1; ++i < nof_children; )
  1795. X  {
  1796. X    SelectEvents (d, children[i], substructure_only);
  1797. X  }
  1798. X
  1799. X  if (nof_children != 0)
  1800. X  {
  1801. X    XFree ((Char*) children);
  1802. X  }
  1803. X}
  1804. X
  1805. X
  1806. X
  1807. X/*
  1808. X *  Main function
  1809. X *  -------------
  1810. X */
  1811. XInt  Main (argc, argv)
  1812. XInt     argc;    /* number of arguments */
  1813. XString  argv[];  /* array of arguments  */
  1814. X
  1815. X{
  1816. X  Display*  d;      /* display pointer */
  1817. X  Window    r;      /* root window     */
  1818. X  Int       s;      /* screen index    */
  1819. X  Queue     queue;  /* as it says      */
  1820. X
  1821. X
  1822. X /*
  1823. X  *  Find out whether there actually is a server on the other side...
  1824. X  */
  1825. X  if (   (d = XOpenDisplay ((String) NULL))
  1826. X      == (Display*) NULL
  1827. X     )
  1828. X  {
  1829. X    (Void) exit (PROBLEMS);
  1830. X  }
  1831. X
  1832. X
  1833. X /*
  1834. X  *  Some initializations.
  1835. X  */
  1836. X  ProcessOpts (d, argc, argv);
  1837. X
  1838. X  XSetErrorHandler ((XErrorHandler) FetchFalseAlarm);
  1839. X  CheckConnection (d, argv[0]);
  1840. X  (Void) signal (SIGHUP, (SigHandler) DisableBySignal);
  1841. X
  1842. X  XSync (d, 0);
  1843. X  (Void) sleep (INITIAL_SLEEP);
  1844. X
  1845. X  queue = NewQueue ();
  1846. X
  1847. X  for (s = -1; ++s < ScreenCount (d); )
  1848. X  {
  1849. X    AddToQueue (queue, r = RootWindowOfScreen (ScreenOfDisplay (d, s)));
  1850. X    SelectEvents (d, r, True);
  1851. X  }
  1852. X
  1853. X  if (close_output)
  1854. X  {
  1855. X    (Void) fclose (stdout);
  1856. X    (Void) fclose (stderr);
  1857. X  }
  1858. X
  1859. X
  1860. X /*
  1861. X  *  Main event loop.
  1862. X  */
  1863. X  forever
  1864. X  {
  1865. X    Sleep ();
  1866. X    ProcessEvents (d, queue);
  1867. X    QueryPointer (d);
  1868. X    EvaluateCounter (d);
  1869. X  }
  1870. X}
  1871. SHAR_EOF
  1872. if test 37774 -ne "`wc -c < 'xautolock.c'`"
  1873. then
  1874.     echo shar: error transmitting "'xautolock.c'" '(should have been 37774 characters)'
  1875. fi
  1876. fi # end of overwriting check
  1877. echo shar: extracting "'Makefile.std'" '(477 characters)'
  1878. if test -f 'Makefile.std'
  1879. then
  1880.     echo shar: will not over-write existing file "'Makefile.std'"
  1881. else
  1882. sed 's/^X//' << \SHAR_EOF > 'Makefile.std'
  1883. X#
  1884. X#  Edit these to suit your needs.
  1885. X#
  1886. X#  SystemV is only used to select between fork and vfork. It doesn't hurt
  1887. X#  to have it defined to YES, but if your system has vfork, it's more
  1888. X#  efficient to comment this stuff out.
  1889. X#
  1890. XDEFINES = -DSystemV=YES
  1891. X
  1892. XRM      = /bin/rm -f
  1893. XCC      = cc
  1894. XHDRS    = patchlevel.h
  1895. XSRCS    = xautolock.c
  1896. XOBJS    = xautolock.o
  1897. X
  1898. XLIBS    = -lX11
  1899. X
  1900. Xxautolock: $(SRCS) 
  1901. X    $(RM) $@
  1902. X    $(CC) $(DEFINES) $(SRCS) -o $@ $(LIBS) 
  1903. X
  1904. Xclean:
  1905. X    $(RM) xautolock $(OBJS) core
  1906. SHAR_EOF
  1907. if test 477 -ne "`wc -c < 'Makefile.std'`"
  1908. then
  1909.     echo shar: error transmitting "'Makefile.std'" '(should have been 477 characters)'
  1910. fi
  1911. fi # end of overwriting check
  1912. echo shar: done with directory "'xautolock'"
  1913. cd ..
  1914. #    End of shell archive
  1915. exit 0
  1916.